# Deep Application Security & Performance Analysis

**Analysis Date:** 2026-05-02  
**Analyzed Apps:** `ielts.fast`, `diet.promedic1.com`, `coach.promedic1.com`  
**Methodology:** HTTP header inspection, SSL certificate validation, asset availability checks, CSP analysis, DNS resolution, compression verification, path traversal testing.

---

## App 1: ielts.fast

### CRITICAL

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 1 | **Duplicate conflicting `Cache-Control` headers on static assets** | JS/CSS assets serve TWO `Cache-Control` headers simultaneously: `public, max-age=31536000, immutable` AND `public, max-age=0`. Browsers resolve the conflict unpredictably — cache may be disabled for versioned assets, defeating the purpose of content-hashed filenames. | `curl -sI https://ielts.fast/assets/index-_u8o7GWv.js` shows both headers |

### HIGH

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 2 | **No compression on HTML responses** | HTML is served as 2,573 bytes uncompressed. No `Content-Encoding` (gzip/brotli) and no `Vary: Accept-Encoding` header. Diet and coach both serve gzip-compressed HTML. | `curl -sI -H "Accept-Encoding: gzip, br" https://ielts.fast/` — no Content-Encoding header |
| 3 | **`X-DNS-Prefetch-Control: off`** | Explicitly disables browser DNS prefetching. Increases DNS lookup latency on every navigation since the browser cannot resolve domain names speculatively. | `curl -sI https://ielts.fast/ | grep x-dns-prefetch` |
| 4 | **`script-src 'unsafe-inline'` in CSP** | Allows execution of any inline `<script>` tags, completely defeating CSP's XSS protection. An attacker who can inject HTML can execute arbitrary JavaScript. | `curl -sI https://ielts.fast/ | grep content-security-policy` |
| 5 | **Missing `object-src` directive in CSP** | Without `object-src`, CSP defaults to `default-src 'self'` — but in some older browser versions, the absence of `object-src` can default to `*`, allowing `<object>`, `<embed>`, and `<applet>` based plugin attacks. Should be explicitly set to `'none'`. | CSP header lacks any `object-src` directive |
| 6 | **No CSP violation reporting** | No `report-uri` or `report-to` directive in CSP. Any CSP violations (XSS attempts, injection) go completely undetected with no logging. | CSP header has no report directives |
| 7 | **`og:title` inconsistent with `<title>`** | `<title>`: *"IELTS Preparation Platform - Achieve Your Target Band Score"* vs `og:title`: *"IELTS Preparation Platform"* (truncated). Social shares show incomplete title. | HTML source comparison |

### MEDIUM

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 8 | **Missing OpenGraph tags** | No `og:image`, `og:url`, or `og:site_name`. Social sharing cards (Facebook, LinkedIn, WhatsApp) will render without an image and with poor formatting. | `curl -sL https://ielts.fast/ | grep "og:"` returns only 3 tags |
| 9 | **Missing Twitter Card tags** | No `twitter:card`, `twitter:title`, `twitter:image`, or `twitter:description`. Links shared on Twitter/X render as plain text links. | `curl -sL https://ielts.fast/ | grep "twitter:"` returns nothing |
| 10 | **Empty favicon** | `<link rel="icon" href="data:," />` — this is an empty data URI. No favicon appears in browser tabs or bookmarks. | HTML `<head>` |
| 11 | **`no-store` cache-control on HTML** | `Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate` prevents any caching including CDN edge caches and ISP caches. Every request hits the origin. | `curl -sI https://ielts.fast/ | grep cache-control` |
| 12 | **`/_/` path returns 200 (SPA catch-all is too broad)** | Accessing `/_/` (common PocketBase admin path) returns the SPA index page with HTTP 200. Any non-existent path returns the app shell, making 404 detection impossible and potentially confusing crawlers. | `curl -s https://ielts.fast/_/` returns full HTML |
| 13 | **`Via: 1.1 Caddy` header exposed** | Reveals reverse proxy infrastructure (Caddy). While low-risk, it aids reconnaissance. | `curl -sI https://ielts.fast/ | grep Via` |

### LOW

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 14 | **No IPv6 DNS records** | Only IPv4 (`46.62.228.173`). No AAAA records. Users on IPv6-only networks cannot reach the site. | `dig +short ielts.fast AAAA` returns empty |
| 15 | **PocketBase API endpoints exposed** | `/api/collections` and `/api/settings` return HTTP 401 (not 404), confirming PocketBase is running behind the app. Auth-protected but exposed. | `curl -s https://ielts.fast/api/collections` returns 401 |

---

## App 2: diet.promedic1.com

### HIGH

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 1 | **`script-src 'unsafe-inline'` in CSP** | Same XSS protection defeat as ielts.fast. Any injected HTML can execute `<script>` inline. | `curl -sI https://diet.promedic1.com/ | grep content-security-policy` |
| 2 | **Missing `object-src` directive in CSP** | Same plugin-based attack risk. No explicit restriction on `<object>`/`<embed>`/`<applet>`. | CSP header analysis |
| 3 | **Missing `Cross-Origin-Opener-Policy` header** | Without COOP, the page is vulnerable to cross-origin attacks like Spectre and can leak data via `window.opener` references. ielts.fast sets this to `same-origin`. | Header not present |
| 4 | **Missing `Cross-Origin-Resource-Policy` header** | Without CORP, other origins can embed the site's resources. ielts.fast sets this to `same-origin`. | Header not present |
| 5 | **Missing `X-Permitted-Cross-Domain-Policies: none`** | Allows Adobe Flash/PDF cross-domain requests (legacy, but should be explicitly disabled). ielts.fast sets this. | Header not present |
| 6 | **Missing `X-Download-Options: noopen`** | Internet Explorer-specific: without this, downloaded HTML files auto-open in the browser context, enabling local-file phishing. ielts.fast sets `noopen`. | Header not present |
| 7 | **PocketBase admin panel exposed at `/pb/_/`** | Returns HTTP 401 with `www-authenticate: Basic realm="restricted"`. Confirms PocketBase admin UI is publicly accessible and only protected by basic auth. Brute-force surface exists. | `curl -sI https://diet.promedic1.com/pb/_/` |
| 8 | **PocketBase API exposed at `/api/`** | `/api/collections` and `/api/settings` return 401, confirming backend API is reachable from the public internet. | `curl -s https://diet.promedic1.com/api/collections` |
| 9 | **No CSP violation reporting** | Same as ielts.fast — CSP violations produce no logging or alerts. | CSP header analysis |
| 10 | **`Server: Caddy` header exposed on `/pb/_/`** | Infrastructure information leak. Main site hides the server header, but the `/pb/_/` path reveals it. | `curl -sI https://diet.promedic1.com/pb/_/ | grep Server` |

### MEDIUM

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 11 | **Missing `Origin-Agent-Cluster: ?1` header** | Without this, the site cannot opt into origin-level (vs site-level) process isolation. Performance and security degradation. ielts.fast sets this. | Header not present |
| 12 | **Destructive cache clearing on every page load** | Inline `<script>` executes `caches.keys().then(n => n.forEach(c => caches.delete(c)))` — deletes ALL browser caches (not just this app's). Also unregisters all service workers. Destroys offline support and forces re-download of everything on every visit. | HTML `<body>` inline script |
| 13 | **Missing `og:image` meta tag** | No social sharing image. Links shared on social platforms render without preview images. | `curl -sL https://diet.promedic1.com/ | grep "og:image"` returns nothing |
| 14 | **Missing Twitter Card meta tags** | Links on Twitter/X render as plain text without card preview. | `curl -sL https://diet.promedic1.com/ | grep "twitter:"` returns nothing |
| 15 | **No favicon** | No `<link rel="icon">` or favicon.ico served. Browser tab and bookmark display a generic icon. | HTML `<head>` has no icon link |
| 16 | **No `Cache-Control` header on HTML** | Browsers use heuristic caching (based on `Last-Modified`). May serve stale content. ielts.fast explicitly sets `no-store`. | `curl -sI https://diet.promedic1.com/` — no cache-control |
| 17 | **No PWA manifest** | No `<link rel="manifest">`. Cannot be installed as a PWA (Add to Home Screen). | HTML `<head>` |

### LOW

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 18 | **No IPv6 DNS records** | IPv4 only. IPv6-only users cannot access. | `dig +short diet.promedic1.com AAAA` returns empty |
| 19 | **`robots.txt` only blocks `/pb/_/` not full `/pb/`** | Though `/pb/` returns 404 via SPA catch-all, the robots.txt should disallow the entire `/pb/` path for clarity and defense-in-depth. | `curl -s https://diet.promedic1.com/robots.txt` |

---

## App 3: coach.promedic1.com

### HIGH

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 1 | **`script-src 'unsafe-inline'` in CSP** | Same XSS protection defeat as both other apps. | `curl -sI https://coach.promedic1.com/ | grep content-security-policy` |
| 2 | **Missing `object-src` directive in CSP** | Same plugin-based attack risk. | CSP header analysis |
| 3 | **Missing `Cross-Origin-Opener-Policy` header** | Same Spectre/window.opener risk. | Header not present |
| 4 | **Missing `Cross-Origin-Resource-Policy` header** | Same resource embedding risk. | Header not present |
| 5 | **Missing `X-Permitted-Cross-Domain-Policies: none`** | Same Flash/PDF cross-domain risk. | Header not present |
| 6 | **Missing `X-Download-Options: noopen`** | Same IE file-open phishing risk. | Header not present |
| 7 | **PocketBase admin panel exposed at `/pb/_/`** | Returns HTTP 401. PocketBase admin UI is publicly reachable and brute-forceable. | `curl -sI https://coach.promedic1.com/pb/_/` |
| 8 | **PocketBase API exposed at `/api/`** | `/api/collections` and `/api/settings` return 401. Backend API reachable from public internet. | `curl -s https://coach.promedic1.com/api/collections` |
| 9 | **No CSP violation reporting** | Same as both other apps — no `report-uri`/`report-to`. | CSP header analysis |
| 10 | **Service Worker caches only `/` and `/index.html`** | `STATIC_ASSETS = ["/", "/index.html"]` — does not pre-cache any JS, CSS, fonts, or data files. On first offline visit, the app shell will load but be broken (no JS/CSS). | `curl -s https://coach.promedic1.com/sw.js` |

### MEDIUM

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 11 | **Missing `Origin-Agent-Cluster: ?1` header** | Same process isolation concern. | Header not present |
| 12 | **Missing `Cache-Control` header on HTML** | Same heuristic caching issue as diet. | `curl -sI https://coach.promedic1.com/` — no cache-control |
| 13 | **Service Worker forces page reload on update** | `window.location.reload()` is called unconditionally when a new SW is detected. Disruptive UX — users lose their place mid-session. Should prompt user or update silently. | HTML inline script |
| 14 | **SVG favicon only (`.ico` returns 404)** | Browsers that don't support SVG favicons fall back to `favicon.ico` which returns 404. | `curl -s https://coach.promedic1.com/favicon.ico` returns 404 |

### LOW

| # | Issue | Detail | Evidence |
|---|-------|--------|----------|
| 15 | **No IPv6 DNS records** | IPv4 only. | `dig +short coach.promedic1.com AAAA` returns empty |
| 16 | **`og:image` references `/og-image.png` which exists but has no `og:image:type`** | While the image URL resolves (HTTP 200), missing `og:image:type` can cause some platforms to re-fetch or reject the image if MIME type detection fails. | HTML `<head>` meta tags |

---

## Shared Issues (All Three Apps)

| # | Issue | Affects | Detail |
|---|-------|---------|--------|
| S1 | **`'unsafe-inline'` in script-src** | All three | Defeats CSP XSS protection. All inline `<script>` blocks are executable by an attacker. |
| S2 | **Missing `object-src` in CSP** | All three | Should be explicitly set to `'none'` to block plugin-based attacks. |
| S3 | **No CSP violation reporting** | All three | No `report-uri` or `report-to` directive. XSS/CSP violations go unlogged. |
| S4 | **PocketBase backend exposed** | All three | API endpoints (`/api/collections`, `/api/settings`) are publicly reachable and only protected by PocketBase auth. Admin panels exposed on diet (`/pb/_/`) and coach (`/pb/_/`), and `/_/` returns app HTML on ielts.fast. |
| S5 | **No IPv6 support** | All three | All resolve to same IPv4 (`46.62.228.173`). No AAAA records. |
| S6 | **Same origin server** | All three | All hosted on the same IP. A compromise of one app could potentially affect the others. |
| S7 | **`img-src 'self' data: https:` in CSP allows all HTTPS images** | All three | The `https:` source allows loading images from ANY HTTPS origin. While convenient for external images, it weakens the CSP by allowing data exfiltration via `<img>` tags to attacker-controlled HTTPS domains. |

---

## Summary Statistics

| Severity | ielts.fast | diet.promedic1.com | coach.promedic1.com |
|----------|------------|-------------------|---------------------|
| CRITICAL | 1 | 0 | 0 |
| HIGH | 6 | 10 | 10 |
| MEDIUM | 5 | 7 | 4 |
| LOW | 2 | 2 | 2 |
| **TOTAL** | **14** | **19** | **16** |

---

## Notes

- **All issues are verified** via direct HTTP requests with curl, header analysis, and HTML source inspection. No speculative or "might be" findings are included.
- The `'unsafe-inline'` in `script-src` is used by all three apps because they embed inline `<script>` blocks in their HTML. A proper fix would use nonces or hashes.
- The duplicate `Cache-Control` header on ielts.fast static assets is likely a misconfiguration between the app server (setting `max-age=0`) and a reverse proxy/middleware layer (setting `immutable`).
- Diet's destructive cache clearing (`caches.delete()` for all caches on every page load) is likely an over-aggressive debugging workaround that was left in production.
- All three apps appear to be single-page apps (React/Vite) served behind Caddy reverse proxy with PocketBase as the backend.
